package crond

import (
	"context"
	"fmt"
	"sale-admin/config"
	"sale-admin/internal/app/grpc/client"
	"sale-admin/internal/app/grpc/protoc/devicec"
	"sale-admin/internal/app/grpc/protoc/system_admin"
	"sale-admin/internal/dal"
	"sale-admin/internal/dao"
	"strings"
	"time"

	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/golang-module/carbon/v2"
	"github.com/xuri/excelize/v2"
)

type BatteryPower struct {
	RobotName string `json:"robot_name"`
	Province  string `json:"province"`
	City      string `json:"city"`
	Location  string `json:"location"`
	Battery   int32  `json:"battery"`
}

// 电量报告
// 上午十点推送低于80%的设备
// 下午三点推送低于50%的设备
func BatteryPowerReport() (err error) {
	now := time.Now()
	if now.Hour() != 10 && now.Hour() != 15 {
		return nil
	}
	fmt.Println("BatteryPowerReport time now ", now.Unix())
	// 获取报告配置
	robotConfigList, count, _ := dao.RobotReportConfig{}.List(context.Background(), dal.Q, "", "", 4 /*电量报告*/, 0, 0)
	if count == 0 {
		return nil
	}
	DeviceAdminClient, clientErr := client.GetDeviceAdminClient()
	if clientErr != nil {
		return
	}
	deviceReq := &devicec.DeviceListReq{}
	deviceListRsp, err1 := DeviceAdminClient.DeviceList(context.Background(), deviceReq)
	if deviceListRsp.Code != 0 || deviceListRsp.List == nil || err1 != nil {
		return
	}
	LocationMap := make(map[string]string)
	ProvinceMap := make(map[string]string)
	CityMap := make(map[string]string)
	AreaNameMap := make(map[string]string)
	// GRPC获取设备区域信息
	deviceClient, clientErr := client.GetDeviceAdminClient()
	if clientErr != nil {
		err = clientErr
		return
	}
	locationReq := &devicec.LocationListReq{}
	locationRsp, err := deviceClient.LocationList(context.Background(), locationReq)
	areaIDList := []string{}
	if locationRsp != nil && locationRsp.Code == 0 && err == nil {
		for _, v := range locationRsp.List {
			LocationMap[v.Id] = v.Name
			ProvinceMap[v.Id] = v.ProvinceId
			CityMap[v.Id] = v.CityId
			areaIDList = append(areaIDList, v.ProvinceId)
			areaIDList = append(areaIDList, v.CityId)
		}
	}
	// GRPC获取省市区名称
	SystemAdminClient, clientErr := client.GetSystemAdminClient()
	if clientErr != nil {
		err = clientErr
		return clientErr
	}

	var req system_admin.AreaLisRequest
	req.AreaIDs = areaIDList
	res, err1 := SystemAdminClient.AreaList(context.Background(), &req)
	if err1 != nil {
		logx.Error(context.Background(), "areas error", logx.Any("res", res), logx.Any("err", err.Error()))
		return nil
	}
	for _, v := range res.Areas {
		AreaNameMap[v.ID] = v.Name
	}
	// 低电量阈值
	lowBatteryThreshold := 0
	if now.Hour() == 10 && now.Minute() == 0 && now.Second() == 0 { // 上午十点 80%
		lowBatteryThreshold = 80
	} else if now.Hour() == 15 && now.Minute() == 0 && now.Second() == 0 { // 下午三点 50%
		lowBatteryThreshold = 50
	}
	for _, v := range robotConfigList {
		ConfigRobotList, _, _ := GetRobotConfigDetail(v.ID)
		if len(ConfigRobotList) > 0 {
			lowBatteryRobot := []BatteryPower{}
			for _, robot := range ConfigRobotList {
				for _, device := range deviceListRsp.List {
					if device.RobotId == robot && device.MerchantId != "1" {
						if device.Battery < int32(lowBatteryThreshold) {
							item := BatteryPower{}
							item.RobotName = device.RobotId
							item.Battery = device.Battery
							if locationName, ok := LocationMap[device.LocationId]; ok {
								// 省名称
								if _, ok := AreaNameMap[ProvinceMap[device.LocationId]]; ok {
									item.Province = AreaNameMap[device.ProvinceId]
								}
								// 市名称
								if _, ok := AreaNameMap[CityMap[device.LocationId]]; ok {
									item.City = AreaNameMap[CityMap[device.LocationId]]
								}
								// 商场名称
								item.Location = locationName
							}
							lowBatteryRobot = append(lowBatteryRobot, item)
						}
					}
				}
			}
			if len(lowBatteryRobot) > 0 {
				// 创建excel
				excelURL := CreateBatteryExcel(lowBatteryRobot)
				// 保存数据库
				err1 := dao.RobotReportLog{}.Create(context.Background(), dal.Q, excelURL, 7 /*电量报告*/, strings.Join(ConfigRobotList, ","),
					v.ObjectName, v.WebHookName, v.WebHookAddress, v.Object, v.Object, time.Now(), time.Now())
				// 推送到飞书群聊
				if err1 == nil {
					statusCode, _, err := helper.Net{}.Request(context.Background(), "POST", v.WebHookAddress, nil,
						map[string]interface{}{
							"msg_type": "text",
							"content": map[string]interface{}{
								"text": excelURL,
							},
						},
					)
					if statusCode != 200 || err != nil {
						logx.Error(context.Background(), "电量报告推送error", logx.Any("statusCode", statusCode), logx.Any("error", err))
					} else {
						logx.Error(context.Background(), "电量报告推送success", logx.Any("statusCode", statusCode), logx.Any("error", err))
					}
				} else {
					logx.Error(context.Background(), "电量报告写入error")
				}
			}
		}
	}
	return nil
}

// CreateBatteryExcel 生成电量报告excel
func CreateBatteryExcel(data []BatteryPower) (url string) {
	// 创建资源
	f := excelize.NewFile()
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	// 设置提醒的字体类型
	headStyle, _ := f.NewStyle(&excelize.Style{
		Font: &excelize.Font{
			Color:  "#FF0000",
			Bold:   true,
			Family: "宋体",
			Size:   14,
		},
	})
	contentStyle, _ := f.NewStyle(&excelize.Style{
		Font: &excelize.Font{
			Bold:   true,
			Family: "宋体",
			Size:   14,
		},
	})
	// 设置单元格样式
	f.SetColWidth("Sheet1", "A", "G", 20)            // 设置宽度
	f.SetCellStyle("Sheet1", "A", "G", contentStyle) // 内容的样式
	f.SetCellStyle("Sheet1", "A1", "A1", headStyle)  // 表头样式
	f.SetCellStyle("Sheet1", "B1", "B1", headStyle)
	f.SetCellStyle("Sheet1", "C1", "C1", headStyle)
	f.SetCellStyle("Sheet1", "D1", "D1", headStyle)

	// 以数组方式实现excel数据的填充
	inputData := [][]interface{}{
		{"设备ID", "所在地区", "所在位置", "当前电量"},
	}
	for _, v := range data {
		inputData = append(inputData, []interface{}{
			v.RobotName,
			v.Province + v.City,
			v.Location,
			v.Battery,
		})
	}
	for idx, row := range inputData {
		cell, err := excelize.CoordinatesToCellName(1, idx+1)
		if err != nil {
			fmt.Println(err)
			return
		}
		// 数据写入
		f.SetSheetRow("Sheet1", cell, &row)
	}

	// 根据指定路径保存文件
	uuid, _ := helper.UUID{}.String()
	fileName := "/file/sale-admin/report_excel/battery_report_" + uuid + "-" + carbon.Yesterday().StartOfDay().ToDateString()
	if err := f.SaveAs(fileName + ".xlsx"); err != nil {
		fmt.Println(err)
	}
	return config.Config.BaseUrl + fileName + ".xlsx"
}
